#include "queue.h"
#include "string.h"

queueT
new_queue(void *array, unsigned int dim, unsigned int size)
{
	queueT queue;
	queue.array = array;
	queue.dim = (dim ? dim : 1); /* queue.dim no puede ser cero */
	queue.size = size;
	queue.head = 0;
	queue.tail = 0;
	return queue;
}

int
enqueue(queueT *q, void *element)
{
	if (queue_is_full(q))
		return 0;
	memcpy((char *) q->array + q->tail * q->size, element, q->size);
	q->tail = (q->tail + 1) % q->dim;
	return 1;
}

int
dequeue(queueT *q, void *element)
{
	if (queue_is_empty(q))
		return 0;
	memcpy(element, (char *) q->array + q->head * q->size, q->size);
	q->head = (q->head + 1) % q->dim;
	return 1;
}

int
queue_is_empty(queueT *q)
{
	return (q->head == q->tail);
}

int
queue_is_full(queueT *q)
{
	return (q->head == (q->tail + 1) % q->dim);
}

unsigned int
queue_length(queueT *q)
{
	/* se suma q->dim para asegurarse de que el operando
	 * izquierdo del modulo sea positivo */
	return ((q->dim + q->tail - q->head) % q->dim);
}

int
get_queue_element(queueT *q, void *element, unsigned int i)
{
	if (i >= queue_length(q))
		return 0;
	memcpy(element, (char *) q->array + ((q->head + i) % q->dim)
			* q->size, q->size);
	return 1;
}

unsigned int
get_queue_next_index(queueT *q, unsigned int i)
{
	return ((i >= queue_length(q)) ? 0 : i + 1);
}



